﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Ecobee.Net
{
	/// <summary>
	/// The type of event. Values: hold, demandResponse, sensor, switchOccupancy, vacation, quickSave, today 
	/// </summary>
	[JsonConverter(typeof(CamelCaseStringEnumConverter))]
	public enum EventType
	{
		None,
		/// <summary>
		/// Hold temperature event.
		/// </summary>
		Hold,
		/// <summary>
		/// Demand Response event.
		/// </summary>
		DemandResponse,
		/// <summary>
		/// Sensor generated event.
		/// </summary>
		Sensor,
		/// <summary>
		/// EMS only event to flip unoccupied to occupied, and vice versa. Look at name to determine 
		/// whether "occupied" or "unoccupied".
		/// </summary>
		SwitchOccupancy,
		/// <summary>
		/// Vacation event.
		/// </summary>
		Vacation,
		/// <summary>
		/// Quick Save event.
		/// </summary>
		QuickSave,
		/// <summary>
		/// Today widget generated event.
		/// </summary>
		Today
	}

	/// <summary>
	/// The fan mode during the event. Values: auto, on Default: based on current climate and HVAC mode. 
	/// </summary>
	[JsonConverter(typeof(CamelCaseStringEnumConverter))]
	public enum FanSetMode
	{
		None,
		Auto,
		On
	}

	/// <summary>
	/// The event object represents a scheduled thermostat program change. All events have a start and 
	/// end time during which the thermostat runtime settings will be modified. Events may not be directly 
	/// modified, various Functions provide the capability to modify the calendar events and to modify the 
	/// program. The event list is sorted with events ordered by whether they are currently running and the 
	/// internal priority of each event. It is safe to take the first event which is running and show it as 
	/// the currently running event. When the resume function is used, events are removed in the order they 
	/// are listed here.
	/// </summary>
	public class Event : ApiObject
	{
		#region Private Fields
		private EventType _type = EventType.None;
		private string _name = string.Empty;
		private bool _running = false;
		private DateTime _startDate = DateTime.MinValue;
		private Time _startTime = Time.Empty;
		private DateTime _endDate = DateTime.MinValue;
		private Time _endTime = Time.Empty;
		private bool _isOccupied = false;
		private bool _isCoolOff = false;
		private bool _isHeatOff = false;
		private ApiTemperature _coolHoldTemp = ApiTemperature.Empty;
		private ApiTemperature _heatHoldTemp = ApiTemperature.Empty;
		private FanSetMode _fan = FanSetMode.None;
		private VentilatorSetMode _vent = VentilatorSetMode.None;
		private int _ventilatorMinOnTime = 0;
		private bool _isOptional = false;
		private bool _isTemperatureRelative = false;
		private ApiTemperature _coolRelativeTemp = ApiTemperature.Empty;
		private ApiTemperature _heatRelativeTemp = ApiTemperature.Empty;
		private bool _isTemperatureAbsolute = false;
		private int _dutyCyclePercentage = 0;
		private int _fanMinOnTime = 0;
		private bool _occupiedSensorActive = false;
		private bool _unoccupiedSensorActive = false;
		private int _drRampUpTemp = 0;
		private int _drRampUpTime = 0;
		private string _linkRef = string.Empty;
		#endregion

		[JsonIgnore]
		public override string UniqueKey
		{
			get
			{
				return this.Name;
			}
		}

		/// <summary>
		/// The type of event. Values: hold, demandResponse, sensor, switchOccupancy, vacation, quickSave, today 
		/// </summary>
		[JsonProperty(PropertyName = "type", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		[DefaultValue(EventType.None)]
		public EventType Type
		{
			get
			{
				return _type;
			}
			set
			{
				_type = value;
			}
		}

		/// <summary>
		/// The unique event name. 
		/// </summary>
		[JsonProperty(PropertyName = "name", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		[DefaultValue("")]
		public string Name
		{
			get
			{
				return _name;
			}
			set
			{
				_name = value;
			}
		}

		/// <summary>
		/// Whether the event is currently active or not. 
		/// </summary>
		[JsonProperty(PropertyName = "running", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		public bool Running
		{
			get
			{
				return _running;
			}
			set
			{
				_running = value;
			}
		}

		/// <summary>
		/// The event start date in thermostat local time.
		/// </summary>
		[JsonProperty(PropertyName = "startDate", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		public DateTime StartDate
		{
			get
			{
				return _startDate;
			}
			set
			{
				_startDate = value;
			}
		}

		/// <summary>
		/// The event start time in thermostat local time.
		/// </summary>
		[JsonProperty(PropertyName = "startTime", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		[DefaultValueConverter(typeof(Time), typeof(TimeDefaultConverter), "12:00 AM")]
		public Time StartTime
		{
			get
			{
				return _startTime;
			}
			set
			{
				_startTime = value;
			}
		}

		[JsonIgnore]
		public DateTime StartDateTime
		{
			get
			{
				DateTime returnValue = this.StartDate;

				returnValue = this.StartDate.Add(this.StartTime);

				return returnValue;
			}
		}

		/// <summary>
		/// The event end date in thermostat local time.
		/// </summary>
		[JsonProperty(PropertyName = "endDate", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		public DateTime EndDate
		{
			get
			{
				return _endDate;
			}
			set
			{
				_endDate = value;
			}
		}

		/// <summary>
		/// The event end time in thermostat local time.
		/// </summary>
		[JsonProperty(PropertyName = "endTime", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		[DefaultValueConverter(typeof(Time), typeof(TimeDefaultConverter), "12:00 AM")]
		public Time EndTime
		{
			get
			{
				return _endTime;
			}
			set
			{
				_endTime = value;
			}
		}

		[JsonIgnore]
		public DateTime EndDateTime
		{
			get
			{
				DateTime returnValue = this.EndDate;

				returnValue = this.EndDate.Add(this.EndTime);

				return returnValue;
			}
		}

		/// <summary>
		/// Whether there are persons occupying the property during the event. 
		/// </summary>
		[JsonProperty(PropertyName = "isOccupied", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		public bool IsOccupied
		{
			get
			{
				return _isOccupied;
			}
			set
			{
				_isOccupied = value;
			}
		}

		/// <summary>
		/// Whether cooling will be turned off during the event. 
		/// </summary>
		[JsonProperty(PropertyName = "isCoolOff", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		public bool IsCoolOff
		{
			get
			{
				return _isCoolOff;
			}
			set
			{
				_isCoolOff = value;
			}
		}

		/// <summary>
		/// Whether heating will be turned off during the event. 
		/// </summary>
		[JsonProperty(PropertyName = "isHeatOff", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		public bool IsHeatOff
		{
			get
			{
				return _isHeatOff;
			}
			set
			{
				_isHeatOff = value;
			}
		}

		/// <summary>
		/// The cooling absolute temperature to set. 
		/// </summary>
		[JsonProperty(PropertyName = "coolHoldTemp", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		[DefaultValueConverter(typeof(ApiTemperature), typeof(ApiTemperatureDefaultConverter), 0F)]
		public ApiTemperature CoolHoldTemp
		{
			get
			{
				return _coolHoldTemp;
			}
			set
			{
				_coolHoldTemp = value;
			}
		}

		/// <summary>
		/// The heating absolute temperature to set.
		/// </summary>
		[JsonProperty(PropertyName = "heatHoldTemp", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		[DefaultValueConverter(typeof(ApiTemperature), typeof(ApiTemperatureDefaultConverter), 0F)]
		public ApiTemperature HeatHoldTemp
		{
			get
			{
				return _heatHoldTemp;
			}
			set
			{
				_heatHoldTemp = value;
			}
		}

		/// <summary>
		/// The fan mode during the event. Values: auto, on Default: based on current climate and HVAC mode.
		/// </summary>
		[JsonProperty(PropertyName = "fan", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		public FanSetMode Fan
		{
			get
			{
				return _fan;
			}
			set
			{
				_fan = value;
			}
		}

		/// <summary>
		/// The ventilator mode during the vent. Values: auto, minontime, on, off.
		/// </summary>
		[JsonProperty(PropertyName = "vent", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		public VentilatorSetMode Vent
		{
			get
			{
				return _vent;
			}
			set
			{
				_vent = value;
			}
		}

		/// <summary>
		/// The minimum amount of time the ventilator equipment must stay on on each duty cycle.
		/// </summary>
		[JsonProperty(PropertyName = "ventilatorMinOnTime", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		public int VentilatorMinOnTime
		{
			get
			{
				return _ventilatorMinOnTime;
			}
			set
			{
				_ventilatorMinOnTime = value;
			}
		}

		/// <summary>
		/// Whether this event is mandatory or the end user can cancel it.
		/// </summary>
		[JsonProperty(PropertyName = "isOptional", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		public bool IsOptional
		{
			get
			{
				return _isOptional;
			}
			set
			{
				_isOptional = value;
			}
		}

		/// <summary>
		/// Whether the event is using a relative temperature setting to the currently active program climate.
		/// </summary>
		[JsonProperty(PropertyName = "isTemperatureRelative", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		public bool IsTemperatureRelative
		{
			get
			{
				return _isTemperatureRelative;
			}
			set
			{
				_isTemperatureRelative = value;
			}
		}

		/// <summary>
		/// The relative cool temperature adjustment. 
		/// </summary>
		[JsonProperty(PropertyName = "coolRelativeTemp", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		[DefaultValueConverter(typeof(ApiTemperature), typeof(ApiTemperatureDefaultConverter), 0F)]
		public ApiTemperature CoolRelativeTemp
		{
			get
			{
				return _coolRelativeTemp;
			}
			set
			{
				_coolRelativeTemp = value;
			}
		}

		/// <summary>
		/// The relative heat temperature adjustment. 
		/// </summary>
		[JsonProperty(PropertyName = "heatRelativeTemp", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		[DefaultValueConverter(typeof(ApiTemperature), typeof(ApiTemperatureDefaultConverter), 0F)]
		public ApiTemperature HeatRelativeTemp
		{
			get
			{
				return _heatRelativeTemp;
			}
			set
			{
				_heatRelativeTemp = value;
			}
		}

		/// <summary>
		/// Whether the event uses absolute temperatures to set the values. Default: true for DRs.
		/// </summary>
		[JsonProperty(PropertyName = "isTemperatureAbsolute", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		public bool IsTemperatureAbsolute
		{
			get
			{
				return _isTemperatureAbsolute;
			}
			set
			{
				_isTemperatureAbsolute = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		[JsonProperty(PropertyName = "dutyCyclePercentage", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		public int DutyCyclePercentage
		{
			get
			{
				return _dutyCyclePercentage;
			}
			set
			{
				_dutyCyclePercentage = value;
			}
		}

		/// <summary>
		/// The minimum number of minutes to run the fan each hour. Range: 0-60, Default: 0
		/// </summary>
		[JsonProperty(PropertyName = "fanMinOnTime", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		public int FanMinOnTime
		{
			get
			{
				return _fanMinOnTime;
			}
			set
			{
				_fanMinOnTime = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		[JsonProperty(PropertyName = "occupiedSensorActive", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		public bool OccupiedSensorActive
		{
			get
			{
				return _occupiedSensorActive;
			}
			set
			{
				_occupiedSensorActive = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		[JsonProperty(PropertyName = "unoccupiedSensorActive", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		public bool UnoccupiedSensorActive
		{
			get
			{
				return _unoccupiedSensorActive;
			}
			set
			{
				_unoccupiedSensorActive = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		[JsonProperty(PropertyName = "drRampUpTemp", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		[DefaultValue(0)]
		public int DrRampUpTemp
		{
			get
			{
				return _drRampUpTemp;
			}
			set
			{
				_drRampUpTemp = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		[JsonProperty(PropertyName = "drRampUpTime", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		[DefaultValue(0)]
		public int DrRampUpTime
		{
			get
			{
				return _drRampUpTime;
			}
			set
			{
				_drRampUpTime = value;
			}
		}

		/// <summary>
		/// Unique identifier set by the server to link one or more events and alerts together.
		/// </summary>
		[JsonProperty(PropertyName = "linkRef", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
		[DefaultValue("")]
		public string LinkRef
		{
			get
			{
				return _linkRef;
			}
			set
			{
				_linkRef = value;
			}
		}

		protected override string OnDeserializeKeyValue(dynamic dataObject)
		{
			return dataObject.name;
		}
	}
}
